package com.pic.mgt.controller;

import java.io.IOException;

import com.pic.mgt.file.io.FileOperation;
import com.pic.mgt.log.IgxLog;
import com.pic.mgt.unit.Message;
import com.pic.mgt.unit.Unit;

public abstract class MessageUnitController extends UnitController {
	private Message message;
	
	private boolean isRemoveRedundantConfirmationFileOfMessage;
	
	private FileOperation fileOperation;

	@Override
	public void doUnitAction(Unit unit) {
		this.message = (Message)unit;
		
		/*
		 * 先確認訊息對應的 交易檔案 和 交易檔的確認檔案 是否都存在， 
		 * 因為 "訊息" 容許這二個檔案的值是 Null的(業務則不行)。
		 * 如果二者有一不存在，則視為此次交易不完成，寫 WARN Log後,視設定
		 * 將訊息確認檔直接移除,或移除並備份到ERROR資料匣，然後不再往下做。
		 */
		if (null == this.message.getTransactionFile() ||
			null == this.message.getConfirmationFileForTxFile()) {
			if (this.isRemoveRedundantConfirmationFileOfMessage) {
				try {
					this.fileOperation.deleteFile(this.message.getConfirmationFile());
					
					// ********************** Log **********************
					IgxLog.messageLog.warn(this,
									"'{}' is a incomplete message, lacking of transaction file or confirmation file for transaction file, and has been removed.",
									this.message.getConfirmationFile().getAbsolutePath());
					// ********************** Log **********************
				} catch (IOException e) {
					// ********************** Log **********************
					IgxLog.messageLog.error(this,"337, Removing redundant confirmation file of message '{}' failed: {}",
									this.message.getConfirmationFile().getAbsolutePath(), e.getMessage());
					// ********************** Log **********************
				}
			}
			else {
				boolean isCompleteBackup = 
					super.unitBackup.removeAndBackupErrorUnit(this.message.getConfirmationFile());
				
				if (isCompleteBackup) {
					// ********************** Log **********************
					IgxLog.messageLog.warn(this,
									"'{}' is a incomplete message, lacking of transaction file or confirmation file for transaction file, and has been moved to error backup.",
									this.message.getConfirmationFile().getAbsolutePath());
					// ********************** Log **********************
				}
			}
			return;
		}
		
		
		/*
		 *  再確認是否為有效的端未(由子類別確認)。
		 *  若為無效端末則不繼續往下做。
		 */
		String ineffectiveTerminal = checkIsEffectiveTerminal(message);
		if (null != ineffectiveTerminal) {
			// ********************** Log **********************
			if (IgxLog.messageLog.isWarnMode()) {
				IgxLog.messageLog.warn(this,
						"Message '{}' has been ignored because terminal id '{}' is ineffective.",
						unit.getUnitName(), ineffectiveTerminal);
			}
			// ********************** Log **********************
			
			super.unitBackup.removeAndBackupErrorUnit(message.getConfirmationFile());
			
			return;
		}
		
		
		// ********************** Log **********************
		if (IgxLog.messageLog.isDebugMode()) {
			IgxLog.messageLog.debug(this, "Backuping message '{}'.",
					message.getUnitName());
		}
		// ********************** Log **********************
		
		// 先做訊息備份(訊息確認檔案)
		boolean completeBackup =
			super.unitBackup.backupUnit(this.message);
		if (!completeBackup) {
			return;
		}
		
		// ********************** Log **********************
		if (IgxLog.messageLog.isDebugMode()) {
			IgxLog.messageLog.debug(this, "Backuping message '{}' completed.",
					message.getUnitName());
		}
		// ********************** Log **********************
		
		doMessageAction(this.message);
	}
	
	/**
	 * 子類別判斷是否為有效的端末。
	 * @param unit
	 * @return 回傳為字串。若為 null 表示為有效的端末；若不是 null，則回傳該
	 * 		       無效的端末 ID。
	 */
	protected abstract String checkIsEffectiveTerminal(Message message);
	
	/**
	 * 有 Message 到達時,方法會被觸發。
	 * @param message 到達的 Message
	 */
	public abstract void doMessageAction(Message message);
	
	
	// --- getter and setter ---
	
	public void setRemoveRedundantConfirmationFileOfMessage(
			boolean isRemoveRedundantConfirmationFileOfMessage) {
		this.isRemoveRedundantConfirmationFileOfMessage = isRemoveRedundantConfirmationFileOfMessage;
	}

	public void setFileOperation(FileOperation fileOperation) {
		this.fileOperation = fileOperation;
	} 
	
}
